﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.World;
using Demo_G.O.S.E.ServerEngine.Timer;
using Demo_G.O.S.E.ServerEngine.Common;
using Demo_G.O.S.E.ServerEngine.Network;
using Demo_G.O.S.E.ServerEngine.MobileAI;
using Demo_G.O.S.E.ServerEngine.Network.DLL;
using Demo_G.O.S.E.ServerEngine.BuildScripts;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Server
{
    /// <summary>
    /// 主服务程序(全局唯一)
    /// </summary>
    [MultiThreadedSupportgAttribute("当前的类所有成员都是静态,支持多线程操作")]
    public class BaseServer
    {
        #region zh-CHS 共有常量 | en Public Constants
        /// <summary>
        /// 是否是64位系统
        /// </summary>
        public static readonly bool Is64Bit     = (IntPtr.Size == 8);
        #endregion

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 程序是否使用缓存的程序集
        /// </summary>
        private static bool s_Cache = true;
        /// <summary>
        /// 服务端的配置是否需要改变的类
        /// </summary>
        private static ConfigServer s_ConfigServer = new ConfigServer();
        #endregion

        #region zh-CHS 共有静态属性 | en Public Static Properties
        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 给出整个服务的世界
        /// </summary>
        private static BaseWorld[] s_BaseWorld = new BaseWorld[0];
        #endregion
        /// <summary>
        /// 给出整个服务的世界
        /// </summary>
        public static BaseWorld[] World
        {
            get { return s_BaseWorld; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static Version s_Version = null;
        #endregion
        /// <summary>
        /// 服务程序的版本号
        /// </summary>
        public static Version Version
        {
            get { return s_Version; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static bool s_MultiProcessor = false;
        #endregion
        /// <summary>
        /// 硬件是否是多处理器
        /// </summary>
        public static bool MultiProcessor
        {
            get { return s_MultiProcessor; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static int s_ProcessorCount = 1;
        #endregion
        /// <summary>
        /// 硬件处理器的数量
        /// </summary>
        public static int ProcessorCount
        {
            get { return s_ProcessorCount; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static Assembly s_Assembly  = null;
        #endregion
        /// <summary>
        /// 主服务程序集
        /// </summary>
        public static Assembly Assembly
        {
            get { return s_Assembly; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static string s_ExePath = string.Empty;
        #endregion
        /// <summary>
        /// 主服务程序的全部路径
        /// </summary>
        public static string ExePath
        {
            get { return s_ExePath; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static string s_BaseDirectory = string.Empty;
        #endregion
        /// <summary>
        /// 主服务程序的路径
        /// </summary>
        public static string BaseDirectory
        {
            get { return s_BaseDirectory; }
        }

        /// <summary>
        /// 主服务程序的参数的字符串信息
        /// </summary>
        public static string Arguments
        {
            get
            {
                StringBuilder l_stringBuilder = new StringBuilder();

                if ( Debug == true )
                    Utility.Separate( ref l_stringBuilder, "-Debug", " " );

                if ( Service == true )
                    Utility.Separate( ref l_stringBuilder, "-Service", " " );

                if ( Profiling == true )
                    Utility.Separate( ref l_stringBuilder, "-Profile", " " );

                if ( s_Cache == false )
                    Utility.Separate( ref l_stringBuilder, "-NoCache", " " );

                if ( HaltOnWarning == true )
                    Utility.Separate( ref l_stringBuilder, "-HaltOnWarning", " " );

                return l_stringBuilder.ToString();
            }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 主服务程序是否正在程序关闭中...
        /// </summary>
        private static bool s_Closing = false;
        #endregion
        /// <summary>
        /// 主服务程序是否正在程序关闭中...
        /// </summary>
        public static bool Closing
        {
            get { return s_Closing; }
            set { s_Closing = value; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static bool s_Debug = false;
        #endregion
        /// <summary>
        /// 主服务程序是否正在调试状态
        /// </summary>
        public static bool Debug
        {
            get { return s_Debug; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static bool s_HaltOnWarning = false;
        #endregion
        /// <summary>
        /// 主服务程序的编译出现警告时是否中断编译
        /// </summary>
        internal static bool HaltOnWarning
        {
            get { return s_HaltOnWarning; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static MultiTextWriter s_MultiConOut = null;
        #endregion
        /// <summary>
        /// 主服务程序的控制台调试输出服务信息
        /// </summary>
        public static MultiTextWriter MultiConsoleOut
        {
            get { return s_MultiConOut; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static Process s_Process = null;
        #endregion
        /// <summary>
        /// 主服务程序的本地系统进程
        /// </summary>
        public static Process Process
        {
            get { return s_Process; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static bool s_Service   = false;
        #endregion
        /// <summary>
        /// 主服务程序是否具有服务日志
        /// </summary>
        public static bool Service
        { 
            get { return s_Service; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 
        /// </summary>
        private static Thread s_Thread  = null;
        #endregion
        /// <summary>
        /// 主服务程序的主核心线程
        /// </summary>
        public static Thread Thread
        {
            get { return s_Thread; }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 是否开始对软件进行性能测试和统计
        /// </summary>
        private static bool s_Profiling = false;
        /// <summary>
        /// 性能测试和统计开始的时间
        /// </summary>
        private static DateTime s_ProfileStart = DateTime.MinValue;
        #endregion
        /// <summary>
        /// 是否用来对软件进行性能测试和统计的过程
        /// </summary>
        public static bool Profiling
        {
            get { return s_Profiling; }
            set
            {
                if ( s_Profiling == value )
                    return;
                else
                    s_Profiling = value;

                // 计算已经统计了的时间长度(如果 s_Profiling == true 的话)
                if ( s_ProfileStart > DateTime.MinValue )
                    s_ProfileTime += DateTime.Now - s_ProfileStart;

                // 统计开始的时间
                s_ProfileStart = ( s_Profiling ? DateTime.Now : DateTime.MinValue );
            }
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 性能测试和统计经过的总时间
        /// </summary>
        private static TimeSpan s_ProfileTime = TimeSpan.Zero;
        #endregion
        /// <summary>
        /// 性能测试和统计经过的总时间
        /// </summary>
        public static TimeSpan ProfileTime
        {
            get { return BaseServer.s_ProfileTime; }
        }
        #endregion

        #region zh-CHS 私有静态方法 | en Private Static Method
        /// <summary>
        /// 1) 初始化程序的主要信息(核心(主)线程,进程,程序域,程序目录)
        /// 2) 检测程序实例是否在运行
        /// 3) 初始化程序域的异常错误处理
        /// 4) 获取运行程序的参数处理
        /// 5) 程序详细内容的信息显示
        /// 6) 初始化脚本的编译
        /// 7) 创建世界 运行世界(多线程处理)
        /// 8) 开始命令行(额外的线程处理)
        /// </summary>
        private static bool InsideRunServer(string[] args)
        {
            InitServerMainInfo();

            InitServerIsRun();

            InitServerExceptionDisposal();

            InitServerArgumentsDisposal( args );

            DisplayServerMainInfo();

            if ( InitServerScriptCompiler() == false )
            {
                System.Diagnostics.Debug.WriteLine( "BaseServer.RunServer(...) - InitServerScriptCompiler() == false error!" );
                return false;
            }

            InitServerWorld();

            StartServerCommandlinesDisposal();

            return true;
        }

        /// <summary>
        /// 1) 初始化程序的主要信息(核心(主)线程,进程,程序域,程序目录)
        /// </summary>
        private static void InitServerMainInfo()
        {
            s_Process = Process.GetCurrentProcess();
            s_Assembly = Assembly.GetEntryAssembly();
            s_Version = s_Assembly.GetName().Version;

            s_ExePath = s_Assembly.Location;
            s_BaseDirectory = s_ExePath;
            if ( s_BaseDirectory.Length > 0 )
            {
                s_BaseDirectory = Path.GetDirectoryName( s_BaseDirectory );
                Directory.SetCurrentDirectory( BaseDirectory );
            }

            s_Thread = Thread.CurrentThread;
            if ( s_Thread != null )
                s_Thread.Name = "核心 线程";

            s_ProcessorCount = Environment.ProcessorCount;
            if ( s_ProcessorCount > 1 )
                s_MultiProcessor = true;
        }

        /// <summary>
        /// 2) 检测程序实例是否在运行
        /// </summary>
        private static void InitServerIsRun()
        {
            Process[] l_ProcessArray = Process.GetProcessesByName( Path.GetFileNameWithoutExtension( s_ExePath ) );
            while ( l_ProcessArray.Length > 1 )
            {
                LOGs.WriteLine( LogMessageType.MSG_WARNING, "当前有程序已经运行,等待程序结束......" );

                if ( l_ProcessArray[0].Id == Process.GetCurrentProcess().Id )
                    l_ProcessArray[1].WaitForExit();
                else
                    l_ProcessArray[0].WaitForExit();

                l_ProcessArray = Process.GetProcessesByName( Path.GetFileNameWithoutExtension( s_ExePath ) );
                if ( l_ProcessArray.Length == 1 )
                    break;
            }
        }

        /// <summary>
        /// 3) 初始化程序域的异常错误处理
        /// </summary>
        private static void InitServerExceptionDisposal()
        {
            // 未知的异常处理
            AppDomain.CurrentDomain.UnhandledException  += new UnhandledExceptionEventHandler( CurrentDomain_UnhandledException );
            // 程序终止退出处理
            AppDomain.CurrentDomain.ProcessExit         += new EventHandler( CurrentDomain_ProcessExit );
            // 控制台按(Ctrl+C)处理
            Console.CancelKeyPress                      += new ConsoleCancelEventHandler( Console_CancelKeyPress );
        }

        /// <summary>
        /// 4) 获取运行程序的参数处理
        /// </summary>
        private static void InitServerArgumentsDisposal(string[] args)
        {
            // 完成服务端的基本初始设置后,配置BaseServer一次
            if ( EventConfigServer != null )
                EventConfigServer( ref s_ConfigServer );

            if ( s_ConfigServer.IsChangeDebug )
                s_Debug = s_ConfigServer.Debug;

            if ( s_ConfigServer.IsChangeService )
                s_Service = s_ConfigServer.Service;

            if ( s_ConfigServer.IsChangeProfiling )
                s_Profiling = s_ConfigServer.Profiling;

            if ( s_ConfigServer.IsChangeCache )
                s_Cache = s_ConfigServer.Cache;

            if ( s_ConfigServer.IsChangeHaltOnWarning )
                s_HaltOnWarning = s_ConfigServer.HaltOnWarning;

            if ( s_ConfigServer.IsChangeServerNetConfig )
                ACEServer.Init( s_ConfigServer.m_iServerCachedSize, s_ConfigServer.m_iServerBufferSize, s_ConfigServer.m_iServerManageThreadPoolSize, s_ConfigServer.m_iServerSendThreadPoolSize, s_ConfigServer.m_iServerReceiveThreadPoolSize, s_ConfigServer.m_iServerProcessThreadPoolSize, s_ConfigServer.m_iServerMaxClients, s_ConfigServer.m_iServerOutTimeInterval );
            else
                ACEServer.InitDefault();

            if ( s_ConfigServer.IsChangeClientNetConfig )
                ACEClient.Init( s_ConfigServer.m_iClientCachedSize, s_ConfigServer.m_iClientBufferSize, s_ConfigServer.m_iClientManageThreadPoolSize, s_ConfigServer.m_iClientSendThreadPoolSize, s_ConfigServer.m_iClientReceiveThreadPoolSize, s_ConfigServer.m_iClientProcessThreadPoolSize, s_ConfigServer.m_iClientOutTimeInterval );
            else
                ACEClient.InitDefault();

            foreach ( string strArg in args )
            {
                if ( Insensitive.Equals( strArg, "-Debug" ) )
                    s_Debug = true;
                else if ( Insensitive.Equals( strArg, "-Service" ) )
                    s_Service = true;
                else if ( Insensitive.Equals( strArg, "-Profile" ) )
                    s_Profiling = true;
                else if ( Insensitive.Equals( strArg, "-NoCache" ) )
                    s_Cache = false;
                else if ( Insensitive.Equals( strArg, "-HaltOnWarning" ) )
                    s_HaltOnWarning = true;
            }

            if ( s_Service )
            {
                if ( Directory.Exists( "../Logs" ) == false )
                    Directory.CreateDirectory( "../Logs" );

                if ( s_ConfigServer.IsChangeLogFile )
                    Console.SetOut( s_MultiConOut = new MultiTextWriter( Console.Out, new FileLogger( "../Logs/" + s_ConfigServer.LogFile ) ) );
                else
                    Console.SetOut( s_MultiConOut = new MultiTextWriter( Console.Out, new FileLogger( "../Logs/Console.log" ) ) );
            }
            else
                Console.SetOut( s_MultiConOut = new MultiTextWriter( Console.Out ) );
        }

        /// <summary>
        /// 5) 程序详细内容的信息显示
        /// </summary>
        private static void DisplayServerMainInfo()
        {
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "  MMMMM       MMMMM       MMMM      MMMMMM  " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, " MM   MM     MM   MM     MM  MM     MM      " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, " MM          MM   MM     MM         MM      " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, " MM MMMM     MM   MM      MMMM      MMMMMM  " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, " MM   MM     MM   MM         MM     MM      " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, " MM   MM     MM   MM     MM  MM     MM      " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "  MMMMM   MM  MMMMM   MM  MMMM   MM MMMMMM  " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "            http://www.DemoEMU.com           " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );
            LOGs.WriteLine( LogMessageType.MSG_INFO, "                                            " );

            LOGs.WriteLine(LogMessageType.MSG_INFO, "Demo G.O.S.E 版本 {0}.{1}, 生成 {2}.{3} (c) DemoSoft - H.Q.Cai", Version.Major, Version.Minor, Version.Build, Version.Revision);

            LOGs.WriteLine(LogMessageType.MSG_INFO, "核心: 运行的.NET框架版本 {0}.{1}.{2}", Environment.Version.Major, Environment.Version.Minor, Environment.Version.Build);

            string l_Arguments  = Arguments;
            if (l_Arguments.Length > 0)
                LOGs.WriteLine(LogMessageType.MSG_INFO, "核心: 运行的参数: {0}", l_Arguments);

            if (s_MultiProcessor || Is64Bit)
                LOGs.WriteLine(LogMessageType.MSG_INFO, "核心: 处理器{0}个-优化在<{1}>", s_ProcessorCount, Is64Bit ? "64-系统" : "32-系统");
        }

        /// <summary>
        /// 6) 初始化脚本的编译
        /// </summary>
        private static bool InitServerScriptCompiler()
        {
            while ( ScriptCompiler.Compile( s_Debug, s_Cache ) == false )
            {
                LOGs.WriteLine(LogMessageType.MSG_ERROR, "脚本: 一个或多个脚本编译失败 或者 没有找到脚本文件");
                LOGs.WriteLine(LogMessageType.MSG_INFO, " 脚本: - 按下任意键退出或按下( R )键再次尝试");

                if ( Console.ReadKey( true ).Key != ConsoleKey.R )
                    return false;
            }

            return true;
        }

        /// <summary>
        /// 7) 创建世界 运行世界(多线程处理)
        /// </summary>
        private static void InitServerWorld()
        {
            // 完成服务端的设置以后,在开始时初始化一次BaseServer
            if ( EventInitOnceServer != null )
                EventInitOnceServer();

            // 启动处理时间片的主线程
            TimerThread.StartTimerThread();

            // 启动处理AI系统的主线程
            MobileAIThread.StartMobileAIThread();

            foreach ( BaseWorld baseWorld in s_BaseWorld )
            {
                // 在开始运行世界之前,初始化一次BaseWorld
                baseWorld.OnInitOnce();

                // 读取BaseWorld需要的一些数据
                baseWorld.OnLoad();

                // 启动BaseWorld保存数据的时间片
                baseWorld.StartSaveTimeSlice();

                // 创建World运行世界的线程
                if ( s_ConfigServer.IsChangeWorldThreadCount == true )
                {
                    baseWorld.WorldThread = new Thread[s_ConfigServer.WorldThreadCount];
                    baseWorld.StartThreadPool( s_ConfigServer.WorldThreadCount );
                }
                else
                {
                    baseWorld.WorldThread = new Thread[( BaseServer.ProcessorCount * 2 + 2 )]; // 处理器 * 2 + 3(后备)
                    baseWorld.StartThreadPool( BaseServer.ProcessorCount * 2 + 2 );
                }

                for ( int iIndex = 0; iIndex < baseWorld.WorldThread.Length; iIndex++ )
                {
                    baseWorld.WorldThread[iIndex] = new Thread( new ThreadStart( baseWorld.RunWorld ) );

                    // 可以修改当前的线程级别
                    baseWorld.WorldThread[iIndex].Priority = ThreadPriority.Highest;
                    baseWorld.WorldThread[iIndex].Name = "游戏世界 线程" + ( iIndex + 1 ).ToString();

                    // 开始线程
                    baseWorld.WorldThread[iIndex].Start();
                }

                // 初始化网络客户端在线状态的检查
                baseWorld.StartCheckAllAliveTime();
            }
        }

        /// <summary>
        /// 8) 开始命令行(在主线程处理)
        /// </summary>
        private static void StartServerCommandlinesDisposal()
        {
            while ( s_Closing == false )
            {
                LOGs.WriteLine( LogMessageType.MSG_DOS_PROMPT, "G.O.S.E:>" );

                ConsoleKeyInfo l_KeyInfo = new ConsoleKeyInfo();
                StringBuilder strStringBuilder = new StringBuilder();
                string strReadLine = string.Empty;
                do
                {
                    l_KeyInfo = Console.ReadKey( false );

                    // 回车
                    if ( l_KeyInfo.Key == ConsoleKey.Enter )
                    {
                        strReadLine = strStringBuilder.ToString();
                        strStringBuilder.Remove( 0, strStringBuilder.Length );

                        // 如果输入的键值不为空
                        if ( strReadLine != string.Empty )
                        {
                            LOGs.WriteLine( LogMessageType.MSG_INPUT, string.Empty );
                            break;
                        } else continue;
                    }

                    // 退格
                    if ( l_KeyInfo.Key == ConsoleKey.Backspace )
                    {
                        if ( strStringBuilder.Length > 0 )
                            strStringBuilder.Remove( strStringBuilder.Length - 1, 1 );
                        else continue;
                    }
                    else
                    {
                        // 跳过无效的健值
                        if ( ( (int)l_KeyInfo.Key > 19 && (int)l_KeyInfo.Key < 47 ) == false )
                        {
                            // 最多 255 个有效的字符
                            if ( strStringBuilder.Length < 255 )
                                strStringBuilder.Append( l_KeyInfo.KeyChar );
                            else continue;
                        }
                    }

                    strReadLine = strStringBuilder.ToString();
                    LOGs.WriteLine( LogMessageType.MSG_INPUT, strReadLine );

                } while ( true );

                if ( strReadLine == string.Empty )
                    continue;

                switch ( strReadLine.ToLower() )
                {
                    case "restart":
                    case "-restart":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : Restart - 重启程序", strReadLine );
                        {
                            s_Closing = true;
                            RestartProgram();
                        }
                        break;
                    case "closelog":
                    case "-closelog":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : Closelog - 关闭日志", strReadLine );
                        {
                            LOGs.IsLogFile = false;
                        }
                        break;
                    case "openlog":
                    case "-openlog":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : OpenLog - 开启日志", strReadLine );
                        if ( LOGs.IsLogFile == false )
                        {
                            LOGs.IsLogFile = true;
                        }
                        break;
                    case "timeinfo":
                    case "-timeinfo":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : TimeInfo - 显示时间片信息", strReadLine );
                        {
                            TimeSlice.DumpInfo();
                        }
                        break;
                    case "saveworld":
                    case "-saveworld":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : SaveWorld - 保存游戏世界数据", strReadLine );
                        {
                            foreach ( BaseWorld baseServer in s_BaseWorld )
                                baseServer.OnSave();
                        }
                        break;
                    case "?":
                    case "h":
                    case "-?":
                    case "-h":
                    case "help":
                    case "-help":
                       LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : Help - 命令帮助", strReadLine );
                        {
                            if ( EventCommandLineInfo != null )
                                EventCommandLineInfo();

                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : OpenLog - 开启日志" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : Closelog - 关闭日志" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : Restart - 重启程序" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : TimeInfo - 显示时间片信息" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : SaveWorld - 保存游戏世界数据" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : Quit - 退出程序" );
                            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令帮助 : Exit - 退出程序" );
                        }
                        break;
                    case "quit":
                    case "-quit":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : Quit - 退出程序", strReadLine );
                        {
                            s_Closing = true;
                        }
                        break;
                    case "exit":
                    case "-exit":
                        LOGs.WriteLine( LogMessageType.MSG_NOTICE, "命令({0}) : Exit - 退出程序", strReadLine );
                        {
                            s_Closing = true;
                        }
                        break;
                    default:
                        {
                            // EventCommandLineDisposal是否已经处理过了
                            bool bIsDisposal = false;
                            if ( EventCommandLineDisposal != null )
                                bIsDisposal = EventCommandLineDisposal( strReadLine );

                            if ( strReadLine != string.Empty && bIsDisposal == false )
                                LOGs.WriteLine( LogMessageType.MSG_WARNING, "命令({0}) : 未知的无效命令", strReadLine );
                        }
                        break;
                }
            }

            // 停止全部的世界线程
            foreach ( BaseWorld baseServer in s_BaseWorld )
                baseServer.StopThreadPool();    // 停止世界线程

            WaitAllRegisterThreadExit();

            // 在结束世界之前,调用一次
            foreach ( BaseWorld baseServer in s_BaseWorld )
            {
                // 在结束世界之前,保存一次数据
                baseServer.OnSave();
                baseServer.OnExit();
            }

            // 在结束服务端之前,调用一次
            if ( EventExitServer != null )
                EventExitServer();

            ACEClient.Fini();
            ACEServer.Fini();
        }

        /// <summary>
        /// 重起系统,打开新的执行程序,关闭当前进程
        /// </summary>
        private static void RestartProgram()
        {
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            Process.Start( Path.GetFileName( s_ExePath ) );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当某个线程结束时调用
        /// </summary>
        private static AutoResetEvent s_ExitSignal = new AutoResetEvent( true );
        #endregion
        /// <summary>
        /// 等待全部的线程关闭
        /// </summary>
        private static void WaitAllRegisterThreadExit()
        {
            while ( s_RegisteredThreadCount > 0 )
            {
                // 调用事件告诉一些线程程序将要关闭
                foreach ( BaseWorld baseWorld in s_BaseWorld )
                    baseWorld.SetWorldSignal();

                // 等待线程关闭的事件
                s_ExitSignal.WaitOne( 10, false );
            }

            LOGs.WriteLine( LogMessageType.MSG_NOTICE, "注册线程: 注册入服务的线程全部退出完毕!" );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 表示程序是否是异常退出的
        /// </summary>
        private static bool s_IsTerminating   = false;
        #endregion
        /// <summary>
        /// 未知的异常处理
        /// </summary>
        private static void CurrentDomain_UnhandledException( object sender, UnhandledExceptionEventArgs eventArgs )
        {
            LOGs.WriteLine( LogMessageType.MSG_FATALERROR, eventArgs.IsTerminating ? ">>>致命错误<<< :" : ">>>致命警告<<< :" );
            LOGs.WriteLine( LogMessageType.MSG_FATALERROR, eventArgs.ExceptionObject.ToString() );

            if ( eventArgs.IsTerminating )
            {
                s_IsTerminating = true;

                bool l_bClose   = false;
                try
                {
                    CrashedEventArgs l_EventArgs = new CrashedEventArgs( eventArgs.ExceptionObject as Exception );
                    EventSink.InvokeCrashed( l_EventArgs );
                    l_bClose = l_EventArgs.Close;
                }
                catch { }

                if ( l_bClose == false )
                {
                    try
                    {
                        // foreach数组操作,在多线程中不怕被替换掉(s_BaseWorld),它不同于列表的操作
                        foreach ( BaseWorld baseServer in s_BaseWorld )
                            foreach ( MessagePump messagePump in baseServer.MessagePump )
                                foreach ( Listener listener in messagePump.Listeners )
                                    listener.Dispose();
                    }
                    catch { }

                    LOGs.WriteLine( LogMessageType.MSG_FATALERROR, "致命的异常错误, 按任意键退出!" );
                    Console.ReadLine();
                }

                s_Closing = true;
            }
        }

        /// <summary>
        /// 程序终止退出处理
        /// </summary>
        private static void CurrentDomain_ProcessExit( object sender, EventArgs eventArgs )
        {
            LOGs.WriteLine( LogMessageType.MSG_INFO, "核心: 程序退出中..." );

            // 如果不是异常的关闭
            if ( s_IsTerminating == false )
            {
                try
                {
                    EventSink.InvokeShutdown( new ShutdownEventArgs() );
                }
                catch { }
            }

            LOGs.WriteLine( LogMessageType.MSG_INFO, "核心: 程序退出完成." );
        }

        /// <summary>
        /// 控制台按(Ctrl+C)处理
        /// </summary>
        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            // 无需终止当前进程 控制台键 (Ctrl+C) 。
            // 无法阻止当前进程的终止 控制台键 (Ctrl+Break 无效)
            if ( e.SpecialKey == ConsoleSpecialKey.ControlC ||
                e.SpecialKey == ConsoleSpecialKey.ControlBreak )
                e.Cancel = true;
        }
        #endregion

        #region zh-CHS 内部静态方法 | en Internal Private Static Method
        /// <summary>
        /// 给全部的游戏世界发出信号
        /// </summary>
        internal static void SetAllWorldSignal()
        {
            // 需要保存一个引用的副本,防止多线程添加的时候调用失败的可能
            foreach ( BaseWorld baseWorld in s_BaseWorld )
                baseWorld.SetWorldSignal();
        }

        #region zh-CHS 私有静态成员变量 | en Private Static Member Variables
        /// <summary>
        /// 共在BaseServer中注册的线程数
        /// </summary>
        private static int s_RegisteredThreadCount = 0;
         #endregion
        /// <summary>
        /// 当启动某个新的线程时候需要注册入BaseServer(告诉BaseServer有新的线程已启动)
        /// </summary>
        internal static void BeginRegisterThread()
        {
            Interlocked.Increment( ref s_RegisteredThreadCount );
        }

        /// <summary>
        /// 当关闭某个新的线程时候需要反注册BaseServer(告诉BaseServer有个的线程已停止)
        /// </summary>
        internal static void EndRegisterThread()
        {
            Interlocked.Decrement( ref s_RegisteredThreadCount );

            // 发生事件
            s_ExitSignal.Set();
        }

        /// <summary>
        /// 发生未知的异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        internal static void UnhandledException( object sender, UnhandledExceptionEventArgs eventArgs )
        {
            CurrentDomain_UnhandledException( sender, eventArgs );
        }
        #endregion

        #region zh-CHS 共有静态方法 | en Public Static Method
        /// <summary>
        /// 开始运行主服务架构程序
        /// </summary>
        /// <param name="args"></param>
        /// <param name="baseWorld"></param>
        /// <returns></returns>
        public static bool RunServer( string[] args, BaseWorld baseWorld )
        {
            AddWorld( baseWorld );
            return InsideRunServer( args );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseWorld"></param>
        public static void AddWorld( BaseWorld baseWorld )
        {
            // 创建新的MessagePump数组,添加数据,交换数组数据,不需要锁定,没有引用时自动会回收数据
            BaseWorld[] tempBaseWorld = new BaseWorld[s_BaseWorld.Length + 1];

            for ( int iIndex = 0; iIndex < s_BaseWorld.Length; ++iIndex )
                tempBaseWorld[iIndex] = s_BaseWorld[iIndex];
            tempBaseWorld[s_BaseWorld.Length] = baseWorld;

            s_BaseWorld = tempBaseWorld;
        }
        #endregion

        #region zh-CHS 共有静态事件 | en Public Static Event
        /// <summary>
        /// 主服务初始化时调用
        /// </summary>
        public static event InitOnceServerEventHandler EventInitOnceServer;
        /// <summary>
        /// 主服务退出时调用
        /// </summary>
        public static event ExitServerEventHandler EventExitServer;
        /// <summary>
        /// 主服务退出时调用
        /// </summary>
        public static event CommandLineDisposalEventHandler EventCommandLineDisposal;
        /// <summary>
        /// 主服务退出时调用
        /// </summary>
        public static event CommandLineInfoEventHandler EventCommandLineInfo;
        /// <summary>
        /// 配置主服务的内容时调用
        /// </summary>
        public static event ConfigServerEventHandler EventConfigServer;
        #endregion
    }
}
#endregion